package com.yuexiao.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuexiao.config.RedisUtil;
import com.yuexiao.entity.DishDto;
import com.yuexiao.entity.ResultInfo;
import com.yuexiao.pojo.Category;
import com.yuexiao.pojo.Dish;
import com.yuexiao.pojo.DishFlavor;
import com.yuexiao.pojo.SetmealDish;
import com.yuexiao.service.CategoryService;
import com.yuexiao.service.DishFlavorService;
import com.yuexiao.service.DishService;
import com.yuexiao.mapper.DishMapper;
import com.yuexiao.service.SetmealDishService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author Administrator
 * @description 针对表【dish(菜品管理)】的数据库操作Service实现
 * @createDate 2022-08-10 14:10:57
 */
@Component
@Service(interfaceClass = DishService.class)
@Transactional(rollbackFor = Exception.class)
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish>
        implements DishService {

    @Resource
    private RedisUtil redisUtil;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private DishFlavorService dishFlavorService;
    @Autowired
    private SetmealDishService setmealDishService;


    /**
     * 根据条件分页查询菜品列表
     *
     * @param page     int 当前页
     * @param pageSize int 每页显示条数
     * @param name     String 菜品名称
     * @return Page mybatisplus自带的分页对象
     */
    @Override
    public Page getDishByPage(int page, int pageSize, String name) {

        //首先在redis中查询是否有数据，如果有直接返回
        Page dish = (Page) redisUtil.hget("dish", page + "_" + pageSize + "_" + name);

        if (dish != null) {
            return dish;
        }

        Page<Dish> dishPage = new Page(page, pageSize);
        //如果没有则进入数据库查询
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        //判断菜名是否为空，不为空则拼接查询条件
        if (!"".equals(name) && !Objects.isNull(name) && !"null".equals(name)) {
            queryWrapper.like(Dish::getName, name);
        }
        Page<Dish> selectPage = baseMapper.selectPage(dishPage, queryWrapper);

        //然后根据类目id查询该菜品的类目数据存入dish
        List<Dish> records = selectPage.getRecords();
        for (Dish dish1 : records) {
            dish1.setCategory(categoryService.getById(dish1.getCategoryId()));
        }
        selectPage.setRecords(records);

        //再次判断name，如果name有值则不存入redis，且查询结果空同样不存redis
        if ("".equals(name) || "null".equals(name) || Objects.isNull(name)) {
            if (selectPage != null && selectPage.getTotal() > 0) {
                redisUtil.hset("dish", page + "_" + pageSize + "_" + name, selectPage);
            }
        }

        return selectPage;
    }

    /**
     * 插入菜品数据以及菜品描述
     *
     * @param dishDto DishDTO 封装的菜品实体类
     * @return boolean true or false
     */
    @Override
    public boolean insertWithFlovor(DishDto dishDto) {

        //保存菜品信息
        baseMapper.insert(dishDto);

        //获取到菜品Id
        Long dishId = dishDto.getId();
        //获取到菜品口味
        List<DishFlavor> dishFlavorList = dishDto.getFlavors();
        //收集菜品口味id
        dishFlavorList = dishFlavorList.stream().map((item) -> {
            item.setDishId(dishId);
            return item;
        }).collect(Collectors.toList());

        //保存菜品口味数据
        dishFlavorService.saveBatch(dishFlavorList);

        redisUtil.del("dish");
        redisUtil.del("dishbycid");
        return true;
    }

    /**
     * 根据菜品id查询菜品详情
     *
     * @param id Long 主键id
     * @return DishDto 封装的菜品实体类
     */
    @Override
    public DishDto getDishById(Long id) {

        //创建DishDto实体对象
        DishDto dishDto = new DishDto();

        //根据id查询菜品数据
        Dish dish = baseMapper.selectById(id);

        //存放到实体类
        BeanUtils.copyProperties(dish, dishDto);

        //查询菜品口味信息
        LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(DishFlavor::getDishId, dish.getId());
        List<DishFlavor> list = dishFlavorService.list(queryWrapper);
        dishDto.setFlavors(list);

        //返回结果
        return dishDto;
    }

    /**
     * 更新菜品数据
     *
     * @param dishDto DishDTO 封装的菜品实体类
     * @return boolean true or false
     */
    @Override
    public boolean updateDish(DishDto dishDto) {

        //更新菜品数据
        baseMapper.updateById(dishDto);

        //删除当前菜品对应的口味
        LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DishFlavor::getDishId, dishDto.getId());
        dishFlavorService.remove(queryWrapper);

        //添加新插入的口味数据
        List<DishFlavor> flavors = dishDto.getFlavors();
        flavors = flavors.stream().map((item) -> {
            item.setDishId(dishDto.getId());
            return item;
        }).collect(Collectors.toList());
        dishFlavorService.saveBatch(flavors);

        //清除redis中数据
        redisUtil.del("dish");
        redisUtil.del("dishbycid");
        return true;
    }

    /**
     * 修改菜品上架状态
     *
     * @param status int 要修改的状态
     * @param ids    Longp[] 主键数组
     * @return boolean true or false
     */
    @Override
    public boolean updatedDishStatusByIds(int status, Long[] ids) {

        //判断如果是要修改为下架状态，则查询套餐关联列表下是否有关联数据
        if (status == 0) {
            LambdaQueryWrapper<SetmealDish> setmealDishLambdaQueryWrapper = new LambdaQueryWrapper<>();
            setmealDishLambdaQueryWrapper.in(SetmealDish::getDishId, ids);
            List<SetmealDish> list = setmealDishService.list(setmealDishLambdaQueryWrapper);
            if (list != null && list.size() > 0) {
                throw new RuntimeException("该菜品有关联套餐");
            }
        }

        for (Long id : ids) {
            Dish dish = new Dish();
            dish.setId(id);
            dish.setStatus(status);
            baseMapper.updateById(dish);
        }
        //清除redis中数据
        redisUtil.del("dish");
        redisUtil.del("dishbycid");
        return true;
    }

    /**
     * 根据id数组删除菜品数据
     *
     * @param ids Longp[] 主键数组
     * @return boolean true or false
     */
    @Override
    public boolean deleteDishByIds(Long[] ids) {

        //查询套餐关联表中有没有关联的套餐，如果有提示先从套餐中去掉
        LambdaQueryWrapper<SetmealDish> setmealDishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        setmealDishLambdaQueryWrapper.in(SetmealDish::getDishId, ids);
        List<SetmealDish> list = setmealDishService.list(setmealDishLambdaQueryWrapper);
        if (list != null && list.size() > 0) {
            throw new RuntimeException("该菜品有关联套餐");
        }

        //批量删除菜品
        baseMapper.deleteBatchIds(Arrays.asList(ids));

        //根据菜品id循环删除对应的口味数据
        LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(DishFlavor::getDishId, ids);
        dishFlavorService.remove(queryWrapper);


        //清除redis中数据
        redisUtil.del("dish");
        redisUtil.del("dishbycid");
        return true;
    }

    /**
     * 根据分类id查询菜品列表
     *
     * @param id Long 分类id
     * @return List<Dish> 菜品列表
     */
    @Override
    public List<Dish> getDishListByCategoryId(Long id) {
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dish::getCategoryId, id);
        queryWrapper.eq(Dish::getStatus, 1);
        return baseMapper.selectList(queryWrapper);
    }


    /**
     * 根据菜品名模糊查询菜品列表
     *
     * @param name String 菜品名称
     * @return List<Dish> 菜品列表
     */
    @Override
    public List<Dish> getDishListByName(String name) {
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Dish::getName, name);
        return baseMapper.selectList(queryWrapper);
    }


    /**
     * 根据分类id查询已上架的菜品
     *
     * @param cid    Long 分类id
     * @param status int 菜品状态
     * @return List<Dish> 菜品列表
     */
    @Override
    public List<DishDto> getDishListByCategoryId(Long cid, int status) {

        //首先从redis中获取数据，如果有则直接返回
        Object dishbycid = redisUtil.hget("dishbycid", String.valueOf(cid));
        if (dishbycid != null) {
            return (List<DishDto>) dishbycid;
        }

        List<DishDto> dishDtos = new ArrayList<>();
        //从数据库获取
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dish::getCategoryId, cid);
        queryWrapper.eq(Dish::getStatus, status);
        List<Dish> dishes = baseMapper.selectList(queryWrapper);

        dishDtos = dishes.stream().map((item) -> {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(item, dishDto);

            Long categoryId = item.getCategoryId();//分类id
            // 根据id查询分类对象
            Category category = categoryService.getById(categoryId);
            if (category != null) {
                String categoryName = category.getName();
                dishDto.setCategoryName(categoryName);
            }

            //当前菜品id
            Long dishId = item.getId();
            LambdaQueryWrapper<DishFlavor> dishFlavorLambdaQueryWrapper = new LambdaQueryWrapper<>();
            dishFlavorLambdaQueryWrapper.eq(DishFlavor::getDishId, dishId);
            List<DishFlavor> list = dishFlavorService.list(dishFlavorLambdaQueryWrapper);

            dishDto.setFlavors(list);

            return dishDto;

        }).collect(Collectors.toList());


        //存入redis中
        redisUtil.hset("dishbycid", String.valueOf(cid), dishDtos);

        return dishDtos;
    }


    /**
     * 根据套餐id查询菜品
     *
     * @param sid Long 套餐ID
     * @return List<SetmealDish> 菜品列表
     */
    @Override
    public List<DishDto> getDishListBySetmealId(Long sid) {

        List<DishDto> dishDtos = new ArrayList<>();


        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SetmealDish::getSetmealId, sid);
        List<SetmealDish> list = setmealDishService.list(queryWrapper);

        dishDtos = list.stream().map((item) -> {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(item, dishDto);
            //根据菜品id查询菜品详情
            Dish dish = baseMapper.selectById(item.getDishId());
            BeanUtils.copyProperties(dish, dishDto);
            return dishDto;
        }).collect(Collectors.toList());
        return dishDtos;
    }
}




